Localization: stage translations into the String Catalog (manual)#25713
Open
jkmassel wants to merge 1 commit into
Open
Localization: stage translations into the String Catalog (manual)#25713jkmassel wants to merge 1 commit into
jkmassel wants to merge 1 commit into
Conversation
Collaborator
Generated by 🚫 Danger |
d5697f8 to
a45aaf1
Compare
b558570 to
c5a43d9
Compare
Adds the localize half of the String Catalog pipeline: a manual (non-CI) lane that folds current GlotPress translations for regular, non-plural strings into the existing Localizable.xcstrings as `human ?? AI ?? English`. The catalog isn't the runtime store yet (the app still ships Localizable.strings), so this only pre-populates it for the eventual cutover — nothing users see changes. - `localize_catalog` lane: download current GlotPress translations into a throwaway dir, fold them in (human => `translated`), then AI-fill the rest (=> `needs_review`). Manual only — it calls the translation API (cost) and commits a large catalog; never wired into `download_localized_strings` or CI. - `CatalogStrings.fold_translations!`: pure, reuse-aware fold. An existing valid cell is kept, so re-runs only translate genuinely-new gaps — the catalog's `needs_review` state IS the persistence (no side-store). A human translation from GlotPress supersedes a kept cell on the next fold. - Immutable-key enforcement replaces `reconcile_changed_sources`: reworded English in place is now a hard error, since `xcstringstool sync` silently keeps the old key's translations and would ship stale text. Rewording requires a new key. - `translate_all` keeps completed batches when one fails mid-run, so a partial API failure degrades to English for the remainder instead of dropping the lot. - docs/localization-pipeline.md documents the regular-string fold and the `human ?? AI ?? English` floor — any translation, human or machine, that fails the placeholder gate falls through to the next rung.
c5a43d9 to
cd9b85f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fills the app's String Catalog (
Localizable.xcstrings) with translations — the human translations we already have from GlotPress, plus machine translations for whatever is still untranslated. This gets the catalog ready ahead of moving the app over to String Catalogs. Nothing users see changes.Two things to know
Staged, not shipped. The catalog file is generated, but the app doesn't read it at runtime yet — regular strings still come from the existing
Localizable.strings. This only pre-fills the catalog for the eventual switch-over. Machine translations are markedneeds_review, so they stay clearly separate from reviewed human translations and can sit in the catalog without shipping to anyone.Manual, not automated. These lanes are run by hand, not wired into any release or CI step: a run extracts strings, calls a paid translation API, and commits a large file, so it shouldn't happen on its own. The unit tests still run in CI.
How it works
Three steps, each runnable on its own:
generate_strings_catalog— extracts the English strings from the code into the catalog.download_catalog_strings— downloads the current translations from GlotPress.localize_catalog— adds the human translations, machine-translates whatever's left, and commits.Each string gets the best translation available in each language: a human translation if there is one, otherwise a machine translation, otherwise the English text. Human translations are marked
translated; machine translations and English fallbacks are markedneeds_review.Re-running is cheap. A machine translation already in the catalog is left alone instead of being requested again, and a human translation always replaces a machine one on the next run. Machine translation only happens when an API key is set — without one, the catalog fills from human translations and English. A machine translation is kept only if its format placeholders (
%1$@,%2$d, …) match the English, so a mangled one falls back to English rather than shipping a broken string.Test plan
fastlane/lanes/*_test.rb) — these run in CIrubocopcleanManual run
First
bundle install. A machine-translation run also needs anANTHROPIC_API_KEY— the Fastfile picks it up from~/.wpios-env.default. Without a key the run still works: it fills in the human translations and English only, skips machine translation, and costs nothing — a good way to check the plumbing before spending anything.Run the three lanes, scoped to one well-translated locale to keep it cheap:
generate_strings_catalogextracts the English strings intoLocalizable.xcstrings(~3,900 of them). No network, no cost.download_catalog_stringsdownloads the French translations from GlotPress into a scratch folder. No cost.localize_catalogfills the French translations into the catalog, machine-translates the gaps, and commits.French is well-translated, so most entries come from GlotPress and only a small number fall to machine translation, which keeps the cost for one locale low. A few entries may stay English where a machine translation was rejected for not matching the English placeholders.
localize_catalogprints a per-locale summary at the end, so you can check the result straight from the log — no need to open the catalog:Expect mostly human, a smaller machine count, and only a few still English. The sample lines let you spot-check the machine translations for obvious nonsense.
localize_catalogcommits the catalog, which is a large file. This run is only to check the output and cost, so discard the commit rather than pushing it (git reset --hard HEAD~1). The catalog gets committed for real during the migration, not in this PR.Plurals are handled the same way in a separate PR (#25710), since they live in their own catalog file.